//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Printing;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents.Serialization;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Xps;
using OpenLS.Core;

namespace OpenLS.Spreadsheet.UI
{
    /// <summary>
    /// Helper class to print workbooks and worksheets
    /// </summary>
    public static class SpreadsheetPrinter
    {
        /// <summary>
        /// Send a worksheet to a print queue.
        /// </summary>
        /// <param name="printQueue"></param>
        /// <param name="worksheet"></param>
        public static void SendWorksheet (PrintQueue printQueue, Worksheet worksheet)
        {
            Contract.Requires(printQueue != null);
            Contract.Requires(worksheet != null);
            SendWorksheetNoCommit(printQueue, worksheet);
            printQueue.Commit();
        }
        /// <summary>
        /// Send a worksheet to a print queue.
        /// </summary>
        /// <param name="printQueue"></param>
        /// <param name="worksheet"></param>
        static void SendWorksheetNoCommit(PrintQueue printQueue, Worksheet worksheet)
        {
            Contract.Requires(printQueue != null);
            Contract.Requires(worksheet != null);
            var writer = PrintQueue.CreateXpsDocumentWriter(printQueue);
            WriteWorksheet(writer, worksheet);
        }
	/// <summary>
        /// Write a worksheet to an XPS document writer
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="worksheet"></param>
        public static void WriteWorksheet(XpsDocumentWriter writer, Worksheet worksheet)
        {
            Contract.Requires(writer != null);
            Contract.Requires(worksheet != null);
            var collator = writer.CreateVisualsCollator();
            WriteWorksheet(collator, worksheet);
        }

        /// <summary>
        /// Write a workbook to a collator.
        /// </summary>
        /// <param name="serializerWriterCollator"></param>
        /// <param name="workbook"></param>
        public static void WriteWorkbook(SerializerWriterCollator serializerWriterCollator, Workbook workbook)
        {
            Contract.Requires(serializerWriterCollator != null);
            Contract.Requires(workbook != null);
            foreach (Worksheet worksheet in Enumerable.OfType<Worksheet>(workbook.Sheets))
            {
                WriteWorksheetPartial(serializerWriterCollator, worksheet);
            }
            serializerWriterCollator.EndBatchWrite();
            
        }
        /// <summary>
        /// Send a workbook to a print queue.
        /// </summary>
        /// <param name="printQueue"></param>
        /// <param name="workbook"></param>
        public static void SendWorkbook(PrintQueue printQueue, Workbook workbook)
        {
            Contract.Requires(printQueue != null);
            Contract.Requires(workbook != null);
            var writer = PrintQueue.CreateXpsDocumentWriter(printQueue);

            var collator = writer.CreateVisualsCollator();
            collator.BeginBatchWrite();
            foreach (Worksheet worksheet in Enumerable.OfType<Worksheet>(workbook.Sheets))
            {
                var paginator = WorksheetPaginator.GetPaginator(worksheet);
                var ccs = Enumerable.ToList(Enumerable.Select(paginator.GetPages(), GetControlForPage));
                foreach (var cc in ccs)
                {
                    cc.Dispatcher.Invoke(new ThreadStart(delegate { }), DispatcherPriority.Render);
                    collator.Write(cc);
                } //  SendWorksheetNoCommit(printQueue, worksheet);
            }
            collator.EndBatchWrite();
            printQueue.Commit();
        }
        /// <summary>
        /// Write a workbook to an XPS document writer.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="workbook"></param>
        public static void WriteWorkbook(XpsDocumentWriter writer, Workbook workbook)
        {
            Contract.Requires(writer != null);
            Contract.Requires(workbook != null);
            foreach (Worksheet worksheet in Enumerable.OfType<Worksheet>(workbook.Sheets))
            {
                WriteWorksheet(writer, worksheet);
            }

        }
        /// <summary>
        /// Write a worksheet to a collator.
        /// </summary>
        /// <param name="serializerWriterCollator"></param>
        /// <param name="worksheet"></param>
        public static void WriteWorksheet(SerializerWriterCollator serializerWriterCollator, Worksheet worksheet)
        {
            Contract.Requires(serializerWriterCollator != null);
            Contract.Requires(worksheet != null);
            WriteWorksheetPartial(serializerWriterCollator, worksheet);
            serializerWriterCollator.EndBatchWrite();
        }
        static void WriteWorksheetPartial(SerializerWriterCollator serializerWriterCollator, Worksheet worksheet)
        {
            Contract.Requires(serializerWriterCollator != null);
            Contract.Requires(worksheet != null);
            var paginator = WorksheetPaginator.GetPaginator(worksheet);
            serializerWriterCollator.BeginBatchWrite();
            var ccs = Enumerable.ToList(Enumerable.Select(paginator.GetPages(), GetControlForPage));
            foreach (var cc in ccs)
            {
                cc.Dispatcher.Invoke(new ThreadStart(delegate { }), DispatcherPriority.Render);
                serializerWriterCollator.Write(cc);
            }
/*            foreach (var page in paginator.GetPages())
            {
                WriteWorksheetPage(serializerWriterCollator, page);

            }*/
        }

        static ContentControl GetControlForPage(WorksheetPage page)
        {
            Contract.Requires(page != null);
            Debug.WriteLine("Printing " + page.Number);
            Size size = PaperSizeToSizeConverter.GetSize(page.Worksheet.PageSetup.PaperSize, page.Worksheet.PageSetup.Orientation);
         //   size = WorksheetPaginator.GetSize(page.Worksheet, null);
            var cc = new ContentControl();
            cc.Resources.MergedDictionaries.Add(new WorksheetPageResources());
            
            Grid r = new Grid();
            r.HorizontalAlignment = HorizontalAlignment.Stretch;
            r.VerticalAlignment = VerticalAlignment.Stretch;
            r.Children.Add(new ContentControl {Content = page});
            cc.Content = r;
            cc.Measure(size);
            cc.HorizontalAlignment = HorizontalAlignment.Stretch;
            cc.VerticalContentAlignment = VerticalAlignment.Stretch;
            ;
            Debug.WriteLine("Arranging, size = " + size);
            cc.Arrange(new Rect(new Point(), size));
            // cc.Content = page;
            cc.Width = size.Width;
            cc.Height = size.Height;
             return cc;
        }


    }
}
